package com.ruoyi.pcj.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mashuai.utils.base.MsAssertUtils;
import com.mashuai.utils.base.MsEmptyUtils;
import com.mashuai.utils.toolkit.core.msConverts.MsStreamUtils;
import com.mashuai.utils.toolkit.core.msMp.MsDb;
import com.ruoyi.basis.service.MsBaseServiceImpl;
import com.ruoyi.basis.utils.mp.MpConditionUtils;
import com.ruoyi.basis.utils.mp.MpPageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.pcj.constant.TipConstant;
import com.ruoyi.pcj.domain.PcjTarget;
import com.ruoyi.pcj.domain.PcjUserTarget;
import com.ruoyi.pcj.dto.match.MatchUserAttrDto;
import com.ruoyi.pcj.mapper.PcjUserTargetMapper;
import com.ruoyi.pcj.service.IPcjUserTargetService;
import com.ruoyi.pcj.utils.pcj.PcjUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 用户-目标关系Service业务层处理
 *
 * @author ms
 * @date 2024-03-11
 */
@Service
public class PcjUserTargetServiceImpl extends MsBaseServiceImpl<PcjUserTargetMapper, PcjUserTarget> implements IPcjUserTargetService {

    @Override
    public <E extends IPage<PcjUserTarget>> E page(E page, Wrapper<PcjUserTarget> qw) {
        return baseMapper.selectPage(page, qw);
    }

    /**
     * 查询用户-目标关系列表
     *
     * @param params 聊天室-查询参数 {"pageNum":1,"pageSize":10}
     * @return 用户-目标关系
     */
    @Override
    public IPage<PcjUserTarget> selectPcjUserTargetList(Map<String, Object> params) {
        //获取条件构造器
        QueryWrapper<PcjUserTarget> qw = MpConditionUtils.getQueryWrapper(params, PcjUserTarget.class);
        //分页查询
        Page<PcjUserTarget> page = this.page(MpPageUtils.getPage(params), qw);
        return page;
    }


    /**
     * 根据id查询用户-目标关系
     *
     * @param id 用户-目标关系主键
     * @return 用户-目标关系
     */
    @Override
    public PcjUserTarget selectPcjUserTargetById(String id) {
        //首先获取主表信息
        PcjUserTarget pcjUserTarget = MsDb.getById(id, PcjUserTarget.class);
        return pcjUserTarget;
    }

    /**
     * 回填子表信息
     **/

    /**
     * 新增用户-目标关系
     *
     * @param pcjUserTarget 用户-目标关系
     * @return 结果
     */
    @Override
    public Boolean insertPcjUserTarget(PcjUserTarget pcjUserTarget) {
        //插入主表
        Boolean success = this.insertData(pcjUserTarget);
        return success;
    }

    /**
     * 修改用户-目标关系
     *
     * @param pcjUserTarget 用户-目标关系
     * @return 结果
     */
    @Override
    public Boolean updatePcjUserTarget(PcjUserTarget pcjUserTarget) {
        //修改主表
        Boolean success = this.updateData(pcjUserTarget);
        return success;
    }

    /**
     * 批量删除用户-目标关系
     *
     * @param ids 需要删除的用户-目标关系主键
     * @return 结果
     */
    @Override
    public Boolean deletePcjUserTargetByIds(String[] ids) {

        //删除主表
        Boolean success = this.removeBatchByIds(Arrays.asList(ids));
        return success;
    }

    /**
     * 获取用户目标
     *
     * @return
     */
    @Override
    public List<PcjUserTarget> getUserTarget() {
        Long userId = SecurityUtils.getUserId();
        LambdaQueryWrapper<PcjUserTarget> qw = Wrappers.lambdaQuery();
        qw.eq(PcjUserTarget::getUserId, userId);
        List<PcjUserTarget> userTargetList = baseMapper.selectList(qw);
        return userTargetList;
    }
    /**
     * 根据主表id，删除子表所有数据
     **/
    /**
     * 对外提供的设置默认字段值，id为空新增，不为空更新
     **/
    public void setEntityDefValAuto(PcjUserTarget pcjUserTarget) {
        this.setDefFieldVal(pcjUserTarget);
    }

    @Override
    public void batchSaveData(List<PcjUserTarget> targetList) {
        //更新目标
        if (targetList != null && targetList.size() != 0) {
            for (PcjUserTarget target : targetList) {
                //回填一些基本字段
                if (MsEmptyUtils.isEmpty(target.getId())) {
                    this.setEntityDefValAuto(target);
                    target.setUserId(SecurityUtils.getUserId());
                }
            }
            MsDb.saveOrUpdateBatch(targetList);
        }
    }

    @Override
    public Map<Long, List<PcjUserTarget>> getUserTargetData(List<String> targetIds) {
        LambdaQueryWrapper<PcjUserTarget> qw = Wrappers.lambdaQuery();
        qw.in(PcjUserTarget::getTargetId, targetIds);
        List<PcjUserTarget> data = baseMapper.selectList(qw);
        Map<Long, List<PcjUserTarget>> dataMap = MsStreamUtils.groupByLink(data, PcjUserTarget::getUserId);
        return dataMap;
    }

    @Override
    public List<String> getUserTargetIds(Long userId, Map<String, PcjTarget> allTargetMap) {
        //获取用户目标ids
        List<PcjUserTarget> userTargetList = PcjUtils.getDataByCurUserSeqNoAsc(userId, PcjUserTarget.class);
        MsAssertUtils.objIsNull(userTargetList, TipConstant.MATCH_NO_SET_TARGET);
        List<String> userTargetIds = new ArrayList<>();
        for (PcjUserTarget ut : userTargetList) {
            PcjTarget target = allTargetMap.get(ut.getTargetId());
            if (target != null) {
                //如果是特殊类型的匹配，需要找到相对应的匹配目标id
                if ("1".equals(target.getType())) {
                    PcjTarget pidTarget = allTargetMap.get(target.getPid());
                    if (pidTarget != null) {
                        userTargetIds.add(pidTarget.getId());
                    }
                }
                //非特殊的直接取目标id即可
                else {
                    userTargetIds.add(ut.getTargetId());
                }
            }
        }
        return userTargetIds;
    }


    @Override
    public List<MatchUserAttrDto> getEqualsTargetUserMsg(Long userId, List<Long> existFriendIds, List<String> userTargetIds) {
        //获取与该用户具有相同目标的用户id集合，排除好友和自己
        List<MatchUserAttrDto> equalsUserTargetList = getEqualsUserTargetList(userId, existFriendIds, userTargetIds);
        return equalsUserTargetList;
    }


    /**
     * 获取与该用户具有相同目标的用户id集合，排除好友和自己
     **/
    private List<MatchUserAttrDto> getEqualsUserTargetList(Long userId, List<Long> existFriendIds, List<String> userTargetIds) {
        LambdaQueryWrapper<PcjUserTarget> qw = Wrappers.lambdaQuery();
        qw.ne(PcjUserTarget::getUserId, userId);
        if (existFriendIds.size() != 0) {
            qw.notIn(PcjUserTarget::getTargetId, existFriendIds);
        }
        qw.in(PcjUserTarget::getTargetId, userTargetIds);
        List<PcjUserTarget> equalsUserTargetList = baseMapper.selectList(qw);
        MsAssertUtils.objIsNull(equalsUserTargetList, TipConstant.MATCH_NO_TARGET);
        List<MatchUserAttrDto> resultList = new ArrayList<>();
        for (PcjUserTarget target : equalsUserTargetList) {
            resultList.add(new MatchUserAttrDto(target.getUserId(), target.getTargetId()));
        }
        return resultList;
    }

    @Override
    public void saveUserTarget(List<PcjUserTarget> list) {
        //先删除所有的，在插入
        Long userId = SecurityUtils.getUserId();
        baseMapper.realDeleteUserTarget(userId);
        //重新插入
        for (PcjUserTarget et : list) {
            setEntityDefValAuto(et);
        }
        this.saveOrUpdateBatch(list);
    }

    @Override
    public List<String> getCurUserTargetIds(Long userId, Map<String, PcjTarget> allTargetData) {
        List<PcjUserTarget> data = PcjUtils.getDataByUserId(userId, PcjUserTarget.class);
        MsAssertUtils.objIsNull(data, TipConstant.MATCH_NO_SET_TARGET);
        List<String> targetIds = MsStreamUtils.listStreamMap(data, PcjUserTarget::getTargetId);
        //如果存在特殊目标id，需要其对应的目标也算
        List<String> specialIds = new ArrayList<>();
        for (String targetId : targetIds) {
            PcjTarget target = allTargetData.get(targetId);
            if ("1".equals(target.getType())) {
                specialIds.add(target.getPid());
            }
        }
        targetIds.addAll(specialIds);
        return targetIds;
    }

    @Override
    public List<MatchUserAttrDto> getAccordTargetUserIds(List<Long> excludeFriendIds, List<String> curUserTargetIds) {
        LambdaQueryWrapper<PcjUserTarget> qw = Wrappers.lambdaQuery();
        qw.in(PcjUserTarget::getTargetId, curUserTargetIds);
        qw.notIn(PcjUserTarget::getUserId, excludeFriendIds);
        List<PcjUserTarget> pcjUserTargets = baseMapper.selectList(qw);
        MsAssertUtils.objIsNull(pcjUserTargets, TipConstant.MATCH_NO_TARGET);
        List<MatchUserAttrDto> dtoList = new ArrayList<>();
        for (PcjUserTarget target : pcjUserTargets) {
            dtoList.add(new MatchUserAttrDto(target.getUserId(), target.getTargetId()));
        }
        return dtoList;
    }
}
